/*
 * pretest.c
 *
 *  Created on: 2011-2-22
 *      Author: root
 */
#include "pretest.h"
int 	d_num=0;


void process_arp(const unsigned char buff[])
{

	unsigned char arp_data[42];
	unsigned char op[2];

	int i=0;
	for(i=0;i<42;i++)
		arp_data[i] = buff[i];

	for(i=0;i<4;i++)
	{
		src_ipmac.ip_add[i] = arp_data[28+i];
		des_ipmac.ip_add[i] = arp_data[38+i];
	}

   for(i=0;i<6;i++)
   {
	   src_ipmac.mac_add[i] = arp_data[22+i];
	   des_ipmac.mac_add[i] = arp_data[32+i];
   }

	if(check_arp(buff)==1)
	{
                        //包结构异常
	}


   op[0]=arp_data[20]; //为操作字段赋值
   op[1]=arp_data[21];
   if (op[0]==0x00 && op[1]==0x01)//请求包
   {
	   if(compare(src_ipmac,ipmaclength)==1)
	   {
                        //
       }
   }

   if (op[0]==0x00 && op[1]==0x02)//响应包
   {
      if((compare(src_ipmac,ipmaclength)==1)||(compare(des_ipmac,ipmaclength)==1))
        {
                        //
        }
   }


}

void process_tcp(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;
//   struct iphdr *iph=sbuffptr->nh.iph;
//   if( SNIFFER_MODE)
//   	print_tcph(tcph);

   if(tcph->syn&&!tcph->ack) {
	attack.synflood++;
	if(!attack.synflood)
          memcpy(&attack.synsbuff,sbuffptr,sizeof(struct sbuff));
   }

   check_scan_tcp(sbuffptr);
   check_dos_land(sbuffptr);
   check_dos_winnuke(sbuffptr);
   check_dos_longurl(sbuffptr);
   check_probe_cgi(sbuffptr);

}


void process_udp(const struct sbuff *sbuffptr)
{
//   struct udphdr *udph=sbuffptr->h.udph;

//   if( SNIFFER_MODE)
//   	print_udph(udph);
 }

void process_icmp(const struct sbuff *sbuffptr)
{
//   struct icmphdr *icmph=sbuffptr->h.icmph;
   check_dos_pingofdeath(sbuffptr);
//   if(SNIFFER_MODE)
//   	print_icmph(icmph);
}


void process_igmp(const struct sbuff *sbuffptr)
{

}


//*****************************************************************
void init_arp()
{
	unsigned   long   FirstIP,SecondIP;
	int    DELta =0;				//IP差值，即IP个数
	FirstIP= inet_addr("59.68.180.126");		//开始地址
	SecondIP= inet_addr("59.68.180.255");		//结束地址
//	转换成能直接递增和递减的地址
   FirstIP = Invert_IP(FirstIP);
   SecondIP = Invert_IP(SecondIP);
	DELta = SecondIP - FirstIP +1;
//  这里最合适的方法是自动获取本机所在IP网段，然后进行起始地址和结束地址的计算，
//  由于技术原因，没有实现完全，故人为设定
	int i = 0;
//	每次群发20个不同IP
//	次数是商QUET_NUM，最后一次群发REMANIND_NUM次。
	int QUET_NUM=DELta/20;
	int REMANIND_NUM= DELta%20;


	for(i=0;i<QUET_NUM+1;i++)
	{
		if(i==QUET_NUM)
			scan_mac(FirstIP,REMANIND_NUM);
		else
			scan_mac(FirstIP,20);
	}
}

unsigned   long   Invert_IP(unsigned   long   NormalIp)
{
    unsigned  char b1,b2,b3,b4;
    b1 =  NormalIp & 0x00FF;
    b2 =  (NormalIp >> 8) & 0x00FF;
    b3 =  (NormalIp >> 16) & 0x00FF;
    b4 =  (NormalIp >> 24) & 0x00FF;
    return   (b1 << 24) |(b2 << 16) |(b3 << 8) |b4;
}

int scan_mac(unsigned long FirstIP, int NUM)
{
	unsigned long TempStartIP = FirstIP;
	int sockfd;	//socket
	char send_buff[50];
	char recv_buff[256];
	memset(send_buff,0,sizeof(send_buff));
	memset(recv_buff,0,sizeof(recv_buff));

	if( (sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
	{
		return 0;
	}

	//用一个socket  循环发送netbios-ns包
	int k=0;
	for(k=0;k<NUM;k++)
	{
		struct Q_NETBIOSNS nbns;
//***   构造包结构   ***//
		nbns.tid=0x0000+d_num;
		nbns.flags=0x0000;
		nbns.questions=0x0100;
		nbns.answerRRS=0x0000;
		nbns.authorityRRS=0x0000;
		nbns.additionalRRS=0x0000;
		nbns.name[0]=0x20;nbns.name[1]=0x43;	nbns.name[2]=0x4b;
		int j=0;
		for(j=3;j<34;j++)
			nbns.name[j]=0x41;
		nbns.name[33]=0x00;
    	nbns.type=0x2100;
    	nbns.classe=0x0100;
//***   构造包结构over  ***//
		memcpy(send_buff,&nbns,sizeof(nbns));

		struct sockaddr_in toAddr;
		bzero((char*)&toAddr,sizeof(toAddr));
		toAddr.sin_family = AF_INET;
		toAddr.sin_addr.s_addr = Invert_IP(FirstIP+d_num);
		toAddr.sin_port = htons(137);
		d_num++;

		int send_num =0;
		send_num = sendto(sockfd, send_buff, sizeof(send_buff), 0,
				(struct sockaddr *)&toAddr, sizeof(toAddr) );
	}

	FILE *arp;
//	arp = fopen("mactoip","w+");
//   fclose(arp);
   arp = fopen("mactoip","a+");

	while(1)
	{
		fd_set fdset;
		struct timeval timeout={1,0}; //select等待1秒，1秒轮询，要非阻塞就置0
		//         timeout.tv_sec = 1;
      //         timeout.tv_usec = 0;
		FD_ZERO(&fdset); 			//每次循环都要清空集合，否则不能检测描述符变化
		FD_SET(sockfd,&fdset); 	//添加描述符
		int maxfdp = sockfd+1; 	//描述符最大值加1
		switch(select(maxfdp,&fdset,NULL,NULL,&timeout)) //select使用
		{
			case -1:
				return 0;//select错误，退出程序
			case 0:		//等待超时
				return 0; //再次轮询
			default:
				recvfrom(sockfd, recv_buff, sizeof(recv_buff), 0,
						(struct sockaddr *)NULL, NULL);
				unsigned short int temptid=0;
				memcpy(&temptid,recv_buff,2);
				unsigned long Temp_IP2 = TempStartIP;
				Temp_IP2+=temptid;
				struct sockaddr_in toAddr;
				bzero((char*)&toAddr,sizeof(toAddr));
				toAddr.sin_family = AF_INET;
				toAddr.sin_addr.s_addr =Invert_IP(Temp_IP2);
				toAddr.sin_port = htons(137);
				printf("ip %-16s",inet_ntoa(toAddr.sin_addr));
				fputs(inet_ntoa(toAddr.sin_addr),arp);
// ***这一块有待考究，主要目的就是想把函数传递过来的FirstIP，转化成报文发送的格式 ***//
				int i=0;
				ptr = inet_ntoa(toAddr.sin_addr);
				int lip;
				lip = inet_addr(ptr);
				printf("%X\n",lip);

				int ljop[4];
				ljop[0] = lip&0x000000ff;
				     ljop[1] =lip>>8&0x000000ff;
				          ljop[2] =lip>>16&0x000000ff;
				               ljop[3]= lip>>24&0x000000ff;
				for(i=0;i<4;i++)
				{
//					printf("%X\n",ljop[i]);
					fix_ipmac[fix_num].ip_add[i] = ljop[i];
				}
// ***这一块有待考究，主要目的就是想把函数传递过来的FirstIP，转化成报文发送的格式 ***//
				unsigned short int NumberOfNames = 0;
				memcpy(&NumberOfNames,recv_buff+56,1);

				unsigned char mac[6];
				char *tmp[6];
				for(i=0;i<6;i++)
				{
					tmp[i] = malloc(1*sizeof(char));
					memcpy(&mac[i],recv_buff+57+NumberOfNames*18+i,1);
					printf("%02X",mac[i]);
					sprintf(tmp[i],"%02X",mac[i]);
					fputs(tmp[i],arp);
					if(i!=5)
						printf("-");
					fix_ipmac[fix_num].mac_add[i] = mac[i];
					free(tmp[i]);
				}
				++fix_num;
				printf("\n");
				fputs("\n",arp);
		}
		//return 0;
	}
	fclose(arp);
	return 1;
}

int check_arp(const unsigned char buff[])
{
	unsigned char op[2];
	int i=0;
   op[0] =buff[20];  //为操作字段赋值
   op[1] =buff[21];

	if (op[0]==0x00 && op[1]==0x01) //是请求包
	{
		for(i=0;i<6;i++)
		{
			if(buff[6+i]!=buff[22+i])
				return 1;
		}
		return 0;
    }

	else if (op[0]==0x00 && op[1]==0x02) //是响应包
	        {
	              for(i=0;i<6;i++)
	                {
	            	  	  if(buff[6+i]!=buff[22+i] || buff[i]!=buff[32+i])
	            	  		  return 1;
	                }
	              return 0;
	        }
	else
	    return -1;
}

int compare(ip_mac compare_ipmac,int lengh)
{
	int i,j,flag1;

	for(i=0;i<lengh;i++)
	{
		flag1=0;
		for(j=0;j<4;j++)
		{
			if(fix_ipmac[i].ip_add[j]!=compare_ipmac.ip_add[j])
			{
				flag1=1;
				break;
			}
		}
		if(flag1==0)
		{
			for(j=0;j<6;j++)
			{
				if(fix_ipmac[i].mac_add[j]!=compare_ipmac.mac_add[j])
					return 1;
			}
			return 0;
		}
	}
	return 0;
}

void check_dos_land(const struct sbuff *sbuffptr)
{

   struct iphdr *iph=sbuffptr->nh.iph;
   struct tcphdr *tcph=sbuffptr->h.tcph;

   if(!tcph->syn)
	return;
   if(iph->saddr!=iph->daddr || tcph->source!=tcph->dest)
        return;
   do_log("land",sbuffptr);

}

void check_dos_winnuke(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;

   if(ntohs(tcph->dest)==139&&tcph->urg)
	do_log("winnuke",sbuffptr);
}

void check_dos_longurl(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;
   unsigned char *data=sbuffptr->data;

   if(ntohs(tcph->dest)!=80 || !tcph->ack)
	return;

   if(strlen((char*)data)>=MAX_URL_LEN){
	do_log("Too_long_url",sbuffptr);
	printf("%s",data);
   }
}

void check_probe_cgi(const struct sbuff *sbuffptr)
{

   struct tcphdr *tcph=sbuffptr->h.tcph;
   unsigned char *data=sbuffptr->data;

   if(ntohs(tcph->dest)!=80||!tcph->ack||!tcph->psh)
	return;

   if((char *)strcasestr((char *)data,"showcode.asp")!=NULL)
   	do_log("showcode",sbuffptr);
   if((char *)strcasestr((char *)data,"phf?")!=NULL)
   	do_log("phf",sbuffptr);
   if((char *)strcasestr((char *)data,"/glimpse")!=NULL)
	do_log("glimpse_cgi",sbuffptr);
   if((char *)strcasestr((char *)data,"/htmlscript")!=NULL)
	do_log("htmlscript",sbuffptr);
   if((char *)strcasestr((char *)data,"/bin/sh")!=NULL)
	do_log("/bin/sh",sbuffptr);
   if((char *)strcasestr((char *)data,"test")!=NULL)
	do_log("test",sbuffptr);
   if((char *)strcasestr((char *)data,"asp..")!=NULL)
	do_log("asp..",sbuffptr);
}

void check_scan_tcp(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;
   char alter[100];

   if(tcph->syn&&!tcph->ack/*&&!findport(ntohs(tcph->dest))*/)//syn半开放
   {
	snprintf(alter,sizeof(alter),"SYN_to_unopen_port%d",ntohs(tcph->dest));
	do_log(alter,sbuffptr);
   }
   if(tcph->res2)  //保留位被置数？
	do_log("queso",sbuffptr);
   if(tcph->fin&&!tcph->syn&&!tcph->rst&&!tcph->psh&&!tcph->ack&&!tcph->urg)//fin
	   do_log("fin_scan",sbuffptr);
   if(tcph->fin&&tcph->syn&&!tcph->rst&&!tcph->psh&&!tcph->ack&&!tcph->urg)//syn fin
      	do_log("SF_scan",sbuffptr);
   if(!tcph->fin&&!tcph->syn&&!tcph->rst&&!tcph->psh&&!tcph->ack&&!tcph->urg)//all NULL
      	do_log("NULL_scan",sbuffptr);
   if(tcph->fin&&tcph->syn&&tcph->rst&&tcph->psh&&tcph->ack&&tcph->urg)//all 1
      	do_log("FULL_Xmas_scan",sbuffptr);
   if(tcph->fin&&!tcph->syn&&!tcph->rst&&tcph->psh&&!tcph->ack&&tcph->urg)//..??
      	do_log("XMAS_Scan(FPU)",sbuffptr);

}



void check_dos_pingofdeath(const struct sbuff *sbuffptr)
{
   struct iphdr *iph=sbuffptr->nh.iph;
   if(iph->protocol!=1) return;
   if(strlen( (char*)sbuffptr)>65536)
   do_log("Ping_of_death",sbuffptr);

}


void stats()
{
   struct sbuff *sbuffptr;

   if(attack.synflood>MAX_SYN){
   	sbuffptr=&attack.synsbuff;
	do_log("synflood",sbuffptr);
   }

   bzero(&attack,sizeof(attack));
   alarm(1);
}


void do_log(char *msg,const struct sbuff *sb)
{
/*        time_t	  ticks;
        char      sendbuff[MAXBUFFSIZE];
	struct    iphdr  *iph=sb->nh.iph;


        printf("old_log_buff=%s\n",old_log_buff);

	if(!strcmp(old_log_buff,msg)){
		old_log_buff_count++;
                printf("old_log_buff_count=%d\n",old_log_buff_count);
		return;
	}

        if(old_log_buff_count) {
	ticks=time(NULL);
        bzero(sendbuff,sizeof(sendbuff));

        snprintf(sendbuff,sizeof(sendbuff),
                 "%d %d %s %d %s",

                 inet_ntoa(iph->saddr),
                 inet_ntoa(iph->daddr),
		 "the last message repeated",
		 old_log_buff_count,
                 fillspace((char *)ctime(&ticks))
                 );
if(fputs(sendbuff,logfd)==EOF)
    err_quit("fputs");
        }

	old_log_buff_count=0;
	if(strncpy(old_log_buff,msg,MAXBUFFSIZE)==NULL){
        	printf("strncpy error\n");
	}
        printf("old_log_buff now:%s\n",old_log_buff);
	ticks=time(NULL);
        bzero(sendbuff,sizeof(sendbuff));

        snprintf(sendbuff,sizeof(sendbuff),
                 "%d %d %s %s",

                 inet_ntoa(iph->saddr),
                 inet_ntoa(iph->daddr),
		 msg,

                 fillspace((char *)ctime(&ticks))
                 );
if(fputs(sendbuff,logfd)==EOF)
    err_quit("fputs");
	return;
*/
}
